/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.constant.CommonConstant;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.excel.utils.ExcelUtil;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.enums.*;
import com.comac.ins.isfd.domain.IsfdModelManagementPart;
import com.comac.ins.isfd.domain.IsfdModelManagementTask;
import com.comac.ins.isfd.domain.IsfdModelManagementTaskRefPart;
import com.comac.ins.isfd.domain.bo.*;
import com.comac.ins.isfd.domain.bo.query.IsfdModelManagementTaskQueryBo;
import com.comac.ins.isfd.domain.vo.*;
import com.comac.ins.isfd.mapper.IsfdModelManagementPartMapper;
import com.comac.ins.isfd.mapper.IsfdModelManagementTaskMapper;
import com.comac.ins.isfd.mapper.IsfdModelManagementTaskRefPartMapper;
import com.comac.ins.isfd.service.IIsfdModelManagementCalculateFileService;
import com.comac.ins.isfd.service.IIsfdModelManagementPartService;
import com.comac.ins.isfd.service.IIsfdModelManagementStructureDefinitionTreeService;
import com.comac.ins.isfd.service.IIsfdModelManagementTaskService;
import com.comac.ins.isfd.util.FileUtils;
import com.comac.ins.system.service.ISysDictDataService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;

/**
 * 模型组建任务Service业务层处理
 *
 * @author hxloongs
 * @date 2024-08-22
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class IsfdModelManagementTaskServiceImpl implements IIsfdModelManagementTaskService {

    @Autowired
    private IsfdModelManagementTaskMapper baseMapper;

    @Autowired
    private IsfdModelManagementPartMapper isfdModelManagementPartMapper;

    @Autowired
    private IsfdModelManagementTaskRefPartMapper isfdModelManagementTaskRefPartMapper;

    @Autowired
    private IIsfdModelManagementPartService iIsfdModelManagementPartService;

    @Autowired
    private IIsfdModelManagementCalculateFileService iIsfdModelManagementCalculateFileService;

    @Autowired
    private ISysDictDataService iSysDictDataService;

    @Autowired
    private IIsfdModelManagementStructureDefinitionTreeService iIsfdModelManagementStructureDefinitionTreeService;

    private static final int MAX_QUERY_NUM = 500;



    @Override
    public IsfdModelManagementTaskVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public IsfdModelManagementTaskDetailVo queryDetailVoById(Long id) {
        IsfdModelManagementTaskDetailVo result = new IsfdModelManagementTaskDetailVo();
        IsfdModelManagementTaskVo isfdModelManagementTaskVo = baseMapper.selectVoById(id);
        if (isfdModelManagementTaskVo == null) {
            throw new BaseException("模型组建任务不存在。");
        }
        BeanUtils.copyProperties(isfdModelManagementTaskVo, result);
        // 已选择的零组件
        result.setPartVoList(getPartListByTaskId(id));
        // 计算文件操作记录
        result.setCalculateFileVoList(iIsfdModelManagementCalculateFileService.queryListByTaskId(id));
        return result;
    }

    @Override
    public TableDataInfo<IsfdModelManagementTaskVo> queryPageList(IsfdModelManagementTaskQueryBo bo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(bo.getPageNum());
        pageQuery.setPageSize(bo.getPageSize());
        LambdaQueryWrapper<IsfdModelManagementTask> lqw = buildQueryWrapper(bo);
        Page<IsfdModelManagementTaskVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public List<IsfdModelManagementStructureDefinitionTreeNodeVo> listTree(String modelNumber, String batchNumber) {
        // 查询总的树结构 机型-部段
        List<IsfdModelManagementStructureDefinitionTreeNodeVo> treeNodeVos = iIsfdModelManagementStructureDefinitionTreeService.queryListTree();

        //根据机型编号和批次编号查询树节点
        if (StringUtils.isNotBlank(modelNumber)) {
            treeNodeVos = treeNodeVos.stream().filter(modelVo -> modelNumber.equals(modelVo.getMark())).toList();
            if (StringUtils.isBlank(batchNumber)) {
                //查询最新默认批次
                if (StringUtils.isBlank(batchNumber)) {
                    //查询最新默认批次
                    IsfdModelManagementStructureDefinitionTreeVo batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryDefaultBatch(modelNumber);
                    batchNumber = batchVo.getMark();
                }
            }
            String finalBatchNumber = batchNumber;
            //通过批次编号过滤
            treeNodeVos.forEach(modelVo -> {
                List<IsfdModelManagementStructureDefinitionTreeNodeVo> batchVoList = modelVo.getChildren();
                batchVoList = batchVoList.stream().filter(batchVo -> finalBatchNumber.equals(batchVo.getMark())).toList();
                modelVo.setChildren(batchVoList);
            });
        }

        // 找出所有为部段的叶子节点，并给封装好相应的组件数据，形成 机型-批次-部段-组件的结构
        for (IsfdModelManagementStructureDefinitionTreeNodeVo treeNode : treeNodeVos) {
            findLeafNodesRecursive(treeNode);
        }
        return treeNodeVos;
    }

    /**
     * 找叶子节点 ，并在叶子节点进行再封装
     *
     * @param node 输入的树
     */
    public void findLeafNodesRecursive(IsfdModelManagementStructureDefinitionTreeNodeVo node) {
        if (node == null) {
            return;
        }
        if (CollectionUtils.isEmpty(node.getChildren()) && IsfdStructureDefinitionTreeLevelEnum.SECTION.getValue().equals(node.getLevel())) {
            // 当前节点没有子节点，因此它是叶子节点
            if (node.getParentId() != 0) {
                // 找到批次节点
                IsfdModelManagementStructureDefinitionTreeVo batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryById(node.getParentId());
                // 找到机型节点
                IsfdModelManagementStructureDefinitionTreeVo modelVo = iIsfdModelManagementStructureDefinitionTreeService.queryById(batchVo.getParentId());
                List<IsfdModelManagementPart> partList = isfdModelManagementPartMapper.selectList(new LambdaQueryWrapper<IsfdModelManagementPart>()
                    .eq(IsfdModelManagementPart::getModelNumber, modelVo.getMark())
                    .eq(IsfdModelManagementPart::getBatchNumber, batchVo.getMark())
                    .eq(IsfdModelManagementPart::getSectionNumber, node.getMark())
                    .eq(IsfdModelManagementPart::getFileLevel, PartFileLevelEnum.COMPONENT.getValue())
                    .eq(IsfdModelManagementPart::getFileType, PartFileTypeEnum.PART.getValue()));
                Set<String> componentNumberList = null;
                if (CollectionUtils.isNotEmpty(partList)) {
                    // 去重
                    componentNumberList = new HashSet<>();
                    for (IsfdModelManagementPart part : partList) {
                        componentNumberList.add(part.getComponentNumber());
                    }
                    // 封装部件下的组件
                    List<IsfdModelManagementStructureDefinitionTreeNodeVo> children = new ArrayList<>();
                    for (String componentNumber : componentNumberList) {
                        IsfdModelManagementStructureDefinitionTreeNodeVo child = new IsfdModelManagementStructureDefinitionTreeNodeVo();
                        child.setParentId(node.getId());
                        child.setMark(componentNumber);
                        child.setName(componentNumber);
                        child.setTaskDefault(node.getTaskDefault());
                        child.setLevel(IsfdStructureDefinitionTreeLevelEnum.COMPONENT.getValue());
                        children.add(child);
                    }
                    node.setChildren(children);
                }
            }
        } else {
            // 遍历子节点
            if (CollectionUtils.isNotEmpty(node.getChildren())) {
                for (IsfdModelManagementStructureDefinitionTreeNodeVo child : node.getChildren()) {
                    findLeafNodesRecursive(child);
                }
            }
        }
    }

    @Override
    public List<IsfdModelManagementPartVo> getPartListByTaskId(Long id) {
        List<IsfdModelManagementPartVo> resultList = new ArrayList<>();
        List<IsfdModelManagementTaskRefPart> isfdModelManagementTaskRefParts = isfdModelManagementTaskRefPartMapper.selectList(new LambdaQueryWrapper<IsfdModelManagementTaskRefPart>().eq(IsfdModelManagementTaskRefPart::getTaskId, id));
        if (CollectionUtils.isEmpty(isfdModelManagementTaskRefParts)) {
            return resultList;
        }
        List<Long> partIdList = isfdModelManagementTaskRefParts.stream().map(IsfdModelManagementTaskRefPart::getPartId).toList();
        return iIsfdModelManagementPartService.queryList(partIdList);
    }

    /**
     * 查询符合条件的模型组建任务列表
     *
     * @param bo 查询条件
     * @return 模型组建任务列表
     */
    @Override
    public List<IsfdModelManagementTaskVo> queryList(IsfdModelManagementTaskBo bo) {
        LambdaQueryWrapper<IsfdModelManagementTask> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }


    private LambdaQueryWrapper<IsfdModelManagementTask> buildQueryWrapper(IsfdModelManagementTaskQueryBo bo) {
        LambdaQueryWrapper<IsfdModelManagementTask> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTaskName()), IsfdModelManagementTask::getTaskName, bo.getTaskName());
        lqw.eq(StringUtils.isNotBlank(bo.getModelNumber()), IsfdModelManagementTask::getModelNumber, bo.getModelNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNumber()), IsfdModelManagementTask::getBatchNumber, bo.getBatchNumber());
        lqw.between(bo.getBeginCreateTime() != null && bo.getEndCreateTime() != null,
            IsfdModelManagementTask::getCreateTime, bo.getBeginCreateTime(), bo.getEndCreateTime());
        lqw.orderByDesc(IsfdModelManagementTask::getCreateTime);
        return lqw;
    }

    private LambdaQueryWrapper<IsfdModelManagementTask> buildQueryWrapper(IsfdModelManagementTaskBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdModelManagementTask> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTaskName()), IsfdModelManagementTask::getTaskName, bo.getTaskName());
        lqw.like(StringUtils.isNotBlank(bo.getMoldName()), IsfdModelManagementTask::getMoldName, bo.getMoldName());
        lqw.eq(StringUtils.isNotBlank(bo.getModelNumber()), IsfdModelManagementTask::getModelNumber, bo.getModelNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNumber()), IsfdModelManagementTask::getBatchNumber, bo.getBatchNumber());
        return lqw;
    }

    @Transactional
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        for (Long id : ids) {
            String partPrePath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
                CommonConstant.MODEL_MANAGEMENT_PART_DATA_PREFIX);
            if (StringUtils.isBlank(partPrePath)) {
                throw new BaseException("字典中没有找到文件存储地址的相关配置。");
            }
            Path path = Paths.get(partPrePath + id + ".bdf");
            if (Files.exists(path)) {
                try {
                    Files.delete(path);
                } catch (IOException e) {
                    log.error("删除文件失败", e);
                    throw new BaseException("删除文件失败");
                }
            }
            baseMapper.deleteById(id);
            isfdModelManagementTaskRefPartMapper.delete(new LambdaQueryWrapper<IsfdModelManagementTaskRefPart>()
                .eq(IsfdModelManagementTaskRefPart::getTaskId, id));
        }
        return Boolean.TRUE;
    }

    @Transactional
    @Override
    public IsfdModelManagementTaskSaveVo save(IsfdModelManagementTaskBo isfdModelManagementTaskBo) {
        String actionType = isfdModelManagementTaskBo.getActionType();
        IsfdModelManagementTask po = MapstructUtils.convert(isfdModelManagementTaskBo, IsfdModelManagementTask.class);
        Long taskId = null;
        if (actionType.equals(ActionTypeEnum.ADD.getValue())) {
            // 防止前端误传
            po.setId(null);
            baseMapper.insert(po);
            taskId = po.getId();
            // 批量新增关联关系
            List<IsfdModelManagementTaskRefPart> targetTaskRefParts = new ArrayList<>();
            List<Long> partIds = isfdModelManagementTaskBo.getPartIds();
            for (Long partId : partIds) {
                IsfdModelManagementTaskRefPart isfdModelManagementTaskRefPart = new IsfdModelManagementTaskRefPart();
                isfdModelManagementTaskRefPart.setTaskId(taskId);
                isfdModelManagementTaskRefPart.setPartId(partId);
                targetTaskRefParts.add(isfdModelManagementTaskRefPart);
            }
            isfdModelManagementTaskRefPartMapper.insertBatch(targetTaskRefParts);
            // 生成任务索引文件
            IsfdModelManagementTaskCreateIndexFileParamBo paramBo = new IsfdModelManagementTaskCreateIndexFileParamBo();
            paramBo.setTaskId(taskId);
            paramBo.setBatchNumber(po.getBatchNumber());
            paramBo.setPartIds(partIds);
            paramBo.setActionTypeEnum(ActionTypeEnum.ADD);
            paramBo.setIsfdModelManagementDownLoadTypeEnum(IsfdModelManagementDownLoadTypeEnum.TASK);
            IsfdModelManagementTaskCreateIndexFileResultBo resultBo = createIndexFile(paramBo);
            po.setIndexFilePath(resultBo.getFilePath());
            baseMapper.updateById(po);
        } else if (actionType.equals(ActionTypeEnum.UPDATE.getValue())) {
            baseMapper.updateById(po);
            taskId = po.getId();
        } else {
            throw new BaseException("保存方法没有相关操作类型");
        }
        IsfdModelManagementTaskSaveVo saveVo = new IsfdModelManagementTaskSaveVo();
        saveVo.setTaskId(taskId);
        return saveVo;
    }

    /**
     * 生成组装索引文件
     */
    @Override
    public IsfdModelManagementTaskCreateIndexFileResultBo createIndexFile(IsfdModelManagementTaskCreateIndexFileParamBo bo) {
        ActionTypeEnum actionTypeEnum = bo.getActionTypeEnum();
        IsfdModelManagementDownLoadTypeEnum isfdModelManagementDownLoadTypeEnum = bo.getIsfdModelManagementDownLoadTypeEnum();
        List<Long> partIds = bo.getPartIds();
        Long taskId = bo.getTaskId();
        Long calculateId = bo.getCalculateId();

        IsfdModelManagementTaskCreateIndexFileResultBo resultBo = new IsfdModelManagementTaskCreateIndexFileResultBo();
        String partPrePath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_PART_DATA_PREFIX);
        if (StringUtils.isBlank(partPrePath)) {
            throw new BaseException("字典中没有找到文件存储地址的相关配置。");
        }
        File indexFile = null;
        String filePath = null;
        List<IsfdModelManagementPartVo> partVos = null;
        if (ActionTypeEnum.ADD.getValue().endsWith(actionTypeEnum.getValue())) {
            partVos = iIsfdModelManagementPartService.queryList(partIds);
            //剔除掉紧固件
            partVos = partVos.stream().filter(item -> !StringUtils.startsWith(item.getPartNumber(), "R_")).toList();
            if (CollectionUtils.isEmpty(partVos)) {
                throw new BaseException("任务未选择零件，不能下载！");
            }
            filePath = partPrePath + bo.getBatchNumber() + "/" + taskId + ".bdf";
            List<String> partPaths = partVos.stream().map(IsfdModelManagementPartVo::getIndexPath).toList();

            try {
                indexFile = FileUtils.writeIndexFile(partPaths, filePath);
            } catch (Exception e) {
                log.error("生成索引文件失败", e);
                if (indexFile.exists()) {
                    indexFile.delete();
                }
                throw new BaseException("生成索引文件失败");
            }
            resultBo.setIndexFile(indexFile);
            resultBo.setPartPaths(partPaths);
            resultBo.setPartPrePath(partPrePath);
            resultBo.setFilePath(filePath);
        } else if (ActionTypeEnum.DOWNLOAD.getValue().endsWith(actionTypeEnum.getValue())) {
            if (isfdModelManagementDownLoadTypeEnum != null
                && IsfdModelManagementDownLoadTypeEnum.CALCULATE.getValue().equals(isfdModelManagementDownLoadTypeEnum.getValue())) {
                partVos = iIsfdModelManagementPartService.queryList(partIds);
            } else {
                partVos = getPartListByTaskId(taskId);
            }
            if (CollectionUtils.isEmpty(partVos)) {
                throw new BaseException("任务未选择零件，不能下载！");
            }

            // 组件索引
            Map<String, List<IsfdModelManagementPartVo>> conponentMap = new HashMap<>();
            for (IsfdModelManagementPartVo isfdModelManagementPartVo : partVos) {
                String componentIndex = isfdModelManagementPartVo.getComponentIndex();
                if (conponentMap.containsKey(componentIndex)) {
                    conponentMap.get(componentIndex).add(isfdModelManagementPartVo);
                } else {
                    List<IsfdModelManagementPartVo> partIndexList = new ArrayList<>();
                    partIndexList.add(isfdModelManagementPartVo);
                    conponentMap.put(componentIndex, partIndexList);
                }
            }

            // 部段索引
            Map<String, List<String>> sectionMap = new HashMap<>();
            for (String componentIndex : conponentMap.keySet()) {
                IsfdModelManagementPartVo choseOne = conponentMap.get(componentIndex).get(0);
                String sectionIndex = choseOne.getSectionIndex();
                if (sectionMap.containsKey(sectionIndex)) {
                    sectionMap.get(sectionIndex).add(componentIndex);
                } else {
                    List<String> conpentIndexList = new ArrayList<>();
                    conpentIndexList.add(componentIndex);
                    sectionMap.put(sectionIndex, conpentIndexList);
                }
            }

            // 机型索引
            String targetIndexPath = partVos.get(0).getIndexPath();
            String root = StringUtils.substringBefore(targetIndexPath, "/");
            String modelIndexPath = calculateId == null ? "/" + root + "/" + taskId + ".bdf" : "/" + root + "/" + calculateId + ".bdf";
            List<String> modelList = new ArrayList<>(sectionMap.keySet());

            // 考虑是计算文件的情况
            List<String> boundaryIndexPaths = bo.getBoundaryIndexPaths();
            if (CollectionUtils.isNotEmpty(boundaryIndexPaths)) {
                modelList.addAll(boundaryIndexPaths);
            }
            List<String> loadIndexPaths = bo.getLoadIndexPaths();
            if (CollectionUtils.isNotEmpty(loadIndexPaths)) {
                modelList.addAll(loadIndexPaths);
            }
            List<String> nonstandardIndexPaths = bo.getNonstandardIndexPaths();
            if (CollectionUtils.isNotEmpty(nonstandardIndexPaths)) {
                modelList.addAll(nonstandardIndexPaths);
            }
            List<String> necessaryItemsIndexPaths = bo.getNecessaryItemsIndexPaths();
            if (CollectionUtils.isNotEmpty(necessaryItemsIndexPaths)) {
                modelList.addAll(necessaryItemsIndexPaths);
            }
            //生成所有的索引文件
            List<File> indexFileList = new ArrayList<>();
            try {
                // 机型
                indexFileList.add(FileUtils.writeIndexFile(modelList, modelIndexPath));
                // 部段
                for (String sectionIndexPath : sectionMap.keySet()) {
                    indexFileList.add(FileUtils.writeIndexFile(sectionMap.get(sectionIndexPath), sectionIndexPath));
                }
                // 组件
                for (String conponentIndexPath : conponentMap.keySet()) {
                    List<String> conponentIndexPathList = conponentMap.get(conponentIndexPath).stream().map(IsfdModelManagementPartVo::getIndexPath).collect(Collectors.toList());
                    indexFileList.add(FileUtils.writeIndexFile(conponentIndexPathList, conponentIndexPath));
                }
                resultBo.setIndexFileList(indexFileList);
                resultBo.setPartPaths(partVos.stream().map(IsfdModelManagementPartVo::getIndexPath).collect(Collectors.toList()));
                resultBo.setPartPrePath(partPrePath);
            } catch (Exception e) {
                log.error("生成索引文件失败", e);
                if (CollectionUtils.isEmpty(indexFileList)) {
                    for (File file : indexFileList) {
                        if (file != null && file.exists()) {
                            file.delete();
                        }
                    }
                }
                throw new BaseException("生成索引文件失败");
            }
        } else {
            throw new BaseException("没有相关操作类型!");
        }
        return resultBo;
    }

    @Override
    public void allBomDownload(String modelNumber, String batchNumber, HttpServletResponse response) {
        IsfdModelManagementStructureDefinitionTreeVo batchVo = null;
        if (StringUtils.isBlank(batchNumber)) {
            //查询最新默认批次
            batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryDefaultBatch(modelNumber);
        } else {
            batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(modelNumber, batchNumber, null);
        }
        batchNumber = batchVo.getMark();
        String batchName = batchVo.getName();

        //需要导出的原始数据
        List<IsfdModelManagementPart> partVoList = isfdModelManagementPartMapper.selectList(new LambdaQueryWrapper<IsfdModelManagementPart>()
            .eq(IsfdModelManagementPart::getModelNumber, modelNumber)
            .eq(IsfdModelManagementPart::getBatchNumber, batchNumber)
            .and(qw -> qw.eq(IsfdModelManagementPart::getFileType, PartFileTypeEnum.PART.getValue()).or().eq(IsfdModelManagementPart::getFileType, PartFileTypeEnum.FASTENER.getValue())));

        if (CollectionUtils.isEmpty(partVoList)) {
            throw new BaseException("没有需要下载的零件信息！");
        }

        //需要导出的零件列表
        List<IsfdModelManagementPartExportVo> isfdModelManagementPartExportVoList = new ArrayList<>();
        for (IsfdModelManagementPart part : partVoList) {
            IsfdModelManagementPartExportVo isfdModelManagementPartExportVo = new IsfdModelManagementPartExportVo();
            BeanUtils.copyProperties(part,isfdModelManagementPartExportVo);
            isfdModelManagementPartExportVo.setBatchName(batchName);
            isfdModelManagementPartExportVoList.add(isfdModelManagementPartExportVo);
        }

        // 封装导出的data
        Map<String, Object> data = new HashMap<>();
        String fileName = modelNumber+"_全机模型";
        data.put(fileName, isfdModelManagementPartExportVoList);
        ExcelUtil.exportWithOutTemplateMultiList(data, fileName, IsfdModelManagementPartExportVo.class, response);
    }

    @Override
    public IsfdModelManagementTaskImportVo bomImport(MultipartFile file) {
        IsfdModelManagementTaskImportVo result = new IsfdModelManagementTaskImportVo();
        //不存在的数据
        List<IsfdModelManagementPartExportVo> notExistsPartData = new ArrayList<>();
        //存在的数据
        List<IsfdModelManagementPartOuterVo> existsPartData = new ArrayList<>();

        List<IsfdModelManagementPartExportVo> partExportVos = null;
        try {
            //解析文件
            partExportVos = ExcelUtil.importExcel(file.getInputStream(), IsfdModelManagementPartExportVo.class);
        } catch (IOException e) {
            log.error("文件解析失败！",e);
            throw new BaseException("文件解析失败！");
        }
        List<Long> idList = partExportVos.stream().map(IsfdModelManagementPartExportVo::getId).toList();

        // 数据分批查询
        List<IsfdModelManagementPartVo> isfdModelManagementPartVoList = new ArrayList<>();
        List<List<Long>> partitions = new ArrayList<>();
        if (idList.size()<MAX_QUERY_NUM){
            partitions.add(idList);
        }else {
            int batchSize = idList.size() / MAX_QUERY_NUM +1;
            for (int i = 1; i <= batchSize; i++) {
                int end = Math.min(i*MAX_QUERY_NUM, idList.size());
                partitions.add(idList.subList((i-1)*MAX_QUERY_NUM, end));
            }
        }
        partitions.forEach(partition->{
            isfdModelManagementPartVoList.addAll(isfdModelManagementPartMapper.selectVoBatchIds(partition));
        });

        //校验partId是否存在
        if (isfdModelManagementPartVoList.size() != idList.size()){
            HashMap<Object, Object> map = new HashMap<>();
            isfdModelManagementPartVoList.forEach(partVo->map.put(partVo.getId(),partVo.getId()));

            //部分零件id不存在
            for (IsfdModelManagementPartExportVo partExportVo : partExportVos) {
                boolean isExist = map.containsKey(partExportVo.getId());
                if (!isExist){
                    notExistsPartData.add(partExportVo);
                }
            }
        }else {
            //分批查询
            //零件全部存在
            partitions.forEach(partition->{
                existsPartData.addAll(isfdModelManagementPartMapper.queryList(partition));
            });
        }
        result.setNotExistsPartData(notExistsPartData);
        result.setExistsPartData(existsPartData);
        return result;
    }

    @Override
    public void bdfDownload(Long id, HttpServletResponse response) {
        //查询批次编号
        IsfdModelManagementTaskVo isfdModelManagementTaskVo = baseMapper.selectVoById(id);

        // 1. 生成索引文件
        IsfdModelManagementTaskCreateIndexFileParamBo paramBo = new IsfdModelManagementTaskCreateIndexFileParamBo();
        paramBo.setTaskId(id);
        paramBo.setPartIds(null);
        paramBo.setActionTypeEnum(ActionTypeEnum.DOWNLOAD);
        paramBo.setIsfdModelManagementDownLoadTypeEnum(IsfdModelManagementDownLoadTypeEnum.TASK);
        IsfdModelManagementTaskCreateIndexFileResultBo resultBo = createIndexFile(paramBo);
        List<File> indexFileList = resultBo.getIndexFileList();

        IsfdModelManagementTaskBdfDownLoadBo downLoadBo = new IsfdModelManagementTaskBdfDownLoadBo();
        downLoadBo.setPartPrePath(resultBo.getPartPrePath());
        downLoadBo.setPartPaths(resultBo.getPartPaths());
        downLoadBo.setBatchNumber(isfdModelManagementTaskVo.getBatchNumber());
        // 2. 生成zip包，将索引文件 和 零件 根据指定目录放入到其中
        String zipFileName = id + ".zip";
        try (ServletOutputStream out = response.getOutputStream();
             ZipOutputStream zos = new ZipOutputStream(out)) {
            response.reset();
            response.setHeader("Content-Disposition", "attachment; filename=" + zipFileName);
            response.setContentType("application/zip");
            FileUtils.addPartAndIndexFileToZip(zos, downLoadBo, indexFileList);
            // 3. 完成ZIP输出流
            zos.finish();
        } catch (IOException e) {
            log.error("生成zip包失败", e);
            throw new BaseException("生成zip包失败，下载BDF失败");
        } finally {
            if (CollectionUtils.isNotEmpty(indexFileList)) {
                for (File file : indexFileList) {
                    if (file != null && file.exists()) {
                        file.delete();
                    }
                }
            }
        }
    }


    @Override
    public void bomExport(Long id, HttpServletResponse response) {
        // 获取要导出的原始数据
        List<IsfdModelManagementPartVo> partVos = getPartListByTaskId(id);
        if (CollectionUtils.isEmpty(partVos)) {
            throw new BaseException("任务未选择零件，不能导出BOM文件！");
        }
        List<IsfdModelManagementPartExportVo> isfdModelManagementPartExportVoList = MapstructUtils.convert(partVos, IsfdModelManagementPartExportVo.class);

        // 封装 机型名称、批次名称和部段名称
        Map<String, String> batchMap = new HashMap<>();
        Map<String, String> sectionMap = new HashMap<>();
        for (IsfdModelManagementPartExportVo vo : isfdModelManagementPartExportVoList) {
            String modelNumber = vo.getModelNumber();

            String batchNumber = vo.getBatchNumber();
            String batchKey = modelNumber + "::" + batchNumber;
            if (batchMap.get(batchKey) == null) {
                IsfdModelManagementStructureDefinitionTreeVo batchVo = iIsfdModelManagementStructureDefinitionTreeService
                    .queryOneByQueryIndex(modelNumber, batchNumber, null);
                batchMap.put(batchKey, batchVo.getName());
                vo.setBatchName(batchVo.getName());
            } else {
                vo.setBatchName(batchMap.get(batchKey));
            }

            String sectionNumber = vo.getSectionNumber();
            String sectionKey = modelNumber + "::" + batchNumber + "::" + sectionNumber;
            if (sectionMap.get(sectionKey) == null) {
                IsfdModelManagementStructureDefinitionTreeVo treeVo = iIsfdModelManagementStructureDefinitionTreeService
                    .queryOneByQueryIndex(modelNumber, batchNumber, sectionNumber);
                sectionMap.put(sectionKey, treeVo.getName());
                vo.setSectionName(treeVo.getName());
            } else {
                vo.setSectionName(sectionMap.get(sectionKey));
            }

            vo.setModelName(vo.getModelNumber());
        }

        // 分组
        Map<String, List<IsfdModelManagementPartExportVo>> groupSectionNumberMap = isfdModelManagementPartExportVoList.stream()
            .collect(Collectors.groupingBy(IsfdModelManagementPartExportVo::getSectionName));

        // 封装导出的data
        Map<String, Object> data = new HashMap<>();
        for (String sectionName : groupSectionNumberMap.keySet()) {
            data.put(sectionName, groupSectionNumberMap.get(sectionName));
        }
        ExcelUtil.exportWithOutTemplateMultiList(data, id.toString(), IsfdModelManagementPartExportVo.class, response);
    }
}
